
#include "network_channel.h"
#include "packet_types.h"

#define RANDU ((double)std::rand()/RAND_MAX)

namespace {

unsigned char generate_err_byte(double p)
{
    unsigned char err = 0;
    for (int i = 0; i < 8; ++i) {
        if (RANDU < p) {
            err |= (1 << i);            
        }
    }

    return err;
}

};

// значение вероятности ошибки по умолчанию
double network_channel::m_p = 0.001;

void network_channel::set_error_probability(double p)
{
    m_p = p;
}

network_channel::network_channel(const sc_core::sc_module_name& name) 
: sc_core::sc_module(name)
{
    m_packet_buf = 0;
}

network_channel::~network_channel()
{    
}

void network_channel::write(const packet& pkt)
{
    if (m_packet_buf)
        delete m_packet_buf;
    
    m_packet_buf = const_cast<packet&>(pkt).clone();

    // add noise to signal
    add_noise();
    
    m_packet_written_evt.notify(sc_core::SC_ZERO_TIME);
}

packet* network_channel::read()
{
    packet* pkt = m_packet_buf->clone();
    delete m_packet_buf;
    m_packet_buf = 0;
    
    return pkt;
}

void network_channel::register_port(sc_core::sc_port_base& port,
                                      const char* if_typename)
{
}

const sc_core::sc_event& network_channel::default_event() const
{
    return m_packet_written_evt;
}

void network_channel::add_noise()
{
    // вносим искажения только в поле данных
    if (frame *fr = dynamic_cast<frame *>(m_packet_buf))
    {            
        packet::data_field &data = fr->data;   
        for (int i = 0; i < data.size(); ++i) {
            data[i] ^= generate_err_byte(m_p);                
        }         
    }
}

